﻿using Serilog;
using Serilog.Events;
using Serilog.Sinks.Elasticsearch;
using Serilog.Sinks.MSSqlServer;

namespace App.Serilog
{
    public static class LogSerilog
    {
        /// <summary>
        /// 创建logging日志
        /// </summary>
        /// <param name="sqlTypes">记录方式
        /// 1. msyql
        /// 2. sqlserver
        /// 3. es
        /// 4. file
        /// 只能选中其中一个
        /// </param>
        /// <param name="sqlDnss">
        /// 数据库dns 
        /// 如果是es则是url
        /// 如果是file 则是路径或者不填，默认运行路径
        /// </param>
        public static void CreateLogger(List<string> sqlTypes, List<string> sqlDnss)
        {

            var log = new LoggerConfiguration()
                       .Enrich.FromLogContext()
                       .Enrich.WithProperty("Version", "1.0.0")

#if DEBUG
                       .MinimumLevel.Debug()//最小日志等级
                       .WriteTo.Console() //日志打印到控制台  
#else
                  .MinimumLevel.Error()//最小日志等级
                  .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Information) //日志打印到控制台  
#endif
                       ;

            // 写入到数据库
            if (sqlTypes != null && sqlTypes.Count != 0)
            {
                for (var i = 0; i < sqlTypes.Count; i++)
                {
                    var sqlType = sqlTypes[i];
                    var sqlDns = sqlDnss[i];

                    switch (sqlType.Trim().ToLower())
                    {
                        case "mysql":
                            log.WriteTo.Async(p => p.MySQL(sqlDns, "logs", LogEventLevel.Warning));
                            break;
                        case "sqlserver":
                            log.WriteTo.Async(p => p.MSSqlServer(sqlDns,
                                sinkOptions: new MSSqlServerSinkOptions
                                {
                                    TableName = "logs",
                                    AutoCreateSqlTable = true
                                },
                            restrictedToMinimumLevel: LogEventLevel.Warning));
                            break;
                        case "es":
                            // 将日志记录到 Elasticsearch
                            log.WriteTo.Async(p => p.Elasticsearch(new ElasticsearchSinkOptions(new Uri(sqlDns))));
                            break;
                        case "file":
                            var path = sqlDns;

                            if (string.IsNullOrWhiteSpace(sqlDns))
                            {
                                var runRoomPath = AppDomain.CurrentDomain.BaseDirectory ?? "C";
                                path = runRoomPath;
                            }

                            var LogFilePath = string (string LogEvent) => Path.Combine(path, "Log", "{LogEvent}", "log-.log");

                            //日志打印到文件上
                            log.WriteTo.Logger(p => p.Filter.ByIncludingOnly(w => w.Level == LogEventLevel.Fatal)
                                        .WriteTo.Async(w => w.File(LogFilePath("Fatal"),
                                        rollingInterval: RollingInterval.Day,
                                        rollOnFileSizeLimit: true,
                                        restrictedToMinimumLevel: LogEventLevel.Fatal)))

                               .WriteTo.Logger(p => p.Filter.ByIncludingOnly(w => w.Level == LogEventLevel.Information)
                               .WriteTo.Async(w => w.File(LogFilePath("Info"),
                               rollingInterval: RollingInterval.Day,
                               rollOnFileSizeLimit: true,
                               restrictedToMinimumLevel: LogEventLevel.Information)))

                               .WriteTo.Logger(p => p.Filter.ByIncludingOnly(w => w.Level == LogEventLevel.Warning)
                               .WriteTo.Async(w => w.File(LogFilePath("Warning"),
                               rollingInterval: RollingInterval.Day,
                               rollOnFileSizeLimit: true,
                               restrictedToMinimumLevel: LogEventLevel.Warning)))

                               .WriteTo.Logger(p => p.Filter.ByIncludingOnly(w => w.Level == LogEventLevel.Error)
                               .WriteTo.Async(w => w.File(LogFilePath("Error"),
                               rollingInterval: RollingInterval.Day,
                               rollOnFileSizeLimit: true,
                               restrictedToMinimumLevel: LogEventLevel.Error)));

                            break;
                        default:
                            break;
                    }
                }
            }

            Log.Logger = log.CreateLogger();
            return;
        }

    }
}
